package com.mai4j.maiadmin.service.impl;


import com.mai4j.maiadmin.generated.tables.records.LanguageRecord;
import com.mai4j.maiadmin.misc.DbUtils;
import com.mai4j.maiadmin.model.dto.LanguageDTO;
import com.mai4j.maiadmin.model.dto.PageDTO;
import com.mai4j.maiadmin.model.http.datatables.Datatable;
import com.mai4j.maiadmin.model.http.datatables.Search;
import com.mai4j.maiadmin.service.LanguageService;
import com.mai4j.maiadmin.service.QueryService;
import com.mai4j.maiadmin.support.IdProvider;
import com.mai4j.maiadmin.support.JooqProvider;
import org.apache.commons.lang3.StringUtils;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.SelectWhereStep;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static com.mai4j.maiadmin.generated.Tables.LANGUAGE;

/**
 * 微信公众号请关注: 开源螺丝钉
 * <br>
 * 码云请关注: <a href="https://gitee.com/xiyoufang">https://gitee.com/xiyoufang</a>
 * <br>
 * 哔哩哔哩请关注: <a href="https://space.bilibili.com/438927834">https://space.bilibili.com/438927834</a>
 *
 * @author xiyoufang
 */
@Service
public class LanguageServiceImpl implements LanguageService {

    private final QueryService queryService;

    public LanguageServiceImpl(QueryService queryService) {
        this.queryService = queryService;
    }


    @Cacheable(value = "data", key = "'languages'")
    @Override
    public List<LanguageDTO> list() {
        return JooqProvider.dsl().selectFrom(LANGUAGE)
                .orderBy(LANGUAGE.SORT_ORDER)
                .fetchInto(LanguageDTO.class);
    }

    /**
     * 分页
     *
     * @param datatable datatable
     */
    @Transactional
    @Override
    public PageDTO<LanguageDTO> paginate(Datatable datatable) {
        DSLContext dsl = JooqProvider.dsl();
        SelectWhereStep<LanguageRecord> query = dsl.selectFrom(LANGUAGE);
        String value = Optional.ofNullable(datatable.getSearch()).orElse(new Search()).getValue();
        List<Condition> conditions = new ArrayList<>();
        if (StringUtils.isNotBlank(value)) {
            value = "%" + value + "%";
            conditions.add(LANGUAGE.NAME.like(value).or(LANGUAGE.LANGUAGE_CODE.like(value)));
        }
        query.where(conditions);
        int count = queryService.fetchCount(query).count;
        List<LanguageDTO> languageDTOS = count == 0 ? Collections.emptyList() : query
                .orderBy(LANGUAGE.SORT_ORDER)
                .limit(datatable.getStart(), datatable.getLength())
                .fetchInto(LanguageDTO.class);
        return new PageDTO<>(languageDTOS, DbUtils.getPage(datatable), datatable.getLength(), DbUtils.getTotalPage(count, datatable), count);
    }


    @Caching(
            evict = {
                    @CacheEvict(value = "data", key = "'languages'"),
                    @CacheEvict(value = "data", key = "'language:' + #languageDTO.getLanguageId()")
            }
    )
    @Override
    public LanguageDTO saveOrUpdate(LanguageDTO languageDTO) {
        int count = JooqProvider.dsl()
                .fetchCount(JooqProvider.dsl()
                        .selectFrom(LANGUAGE)
                        .where(LANGUAGE.LANGUAGE_ID.eq(languageDTO.getLanguageId())));
        long languageId = count == 0 ? IdProvider.next() : languageDTO.getLanguageId();
        if (count == 0) {
            JooqProvider.dsl().insertInto(LANGUAGE).columns(
                    LANGUAGE.LANGUAGE_ID,
                    LANGUAGE.LANGUAGE_CODE,
                    LANGUAGE.NAME,
                    LANGUAGE.SORT_ORDER,
                    LANGUAGE.STATUS,
                    LANGUAGE.DATE_ADDED,
                    LANGUAGE.DATE_MODIFIED
            ).values(
                    languageId,
                    languageDTO.getLanguageCode(),
                    languageDTO.getName(),
                    languageDTO.getSortOrder(),
                    languageDTO.getStatus(),
                    LocalDateTime.now(),
                    LocalDateTime.now()).execute();
        } else {
            JooqProvider.dsl().update(LANGUAGE)
                    .set(LANGUAGE.LANGUAGE_CODE, languageDTO.getLanguageCode())
                    .set(LANGUAGE.NAME, languageDTO.getName())
                    .set(LANGUAGE.SORT_ORDER, languageDTO.getSortOrder())
                    .set(LANGUAGE.STATUS, languageDTO.getStatus())
                    .set(LANGUAGE.DATE_MODIFIED, LocalDateTime.now())
                    .where(LANGUAGE.LANGUAGE_ID.eq(languageId)).execute();
        }
        return get(languageId);
    }

    @Caching(
            evict = {
                    @CacheEvict(value = "data", key = "'languages'"),
                    @CacheEvict(value = "data", key = "'language:' + #languageId")
            }
    )
    @Override
    public void delete(Long languageId) {
        JooqProvider.dsl().deleteFrom(LANGUAGE).where(LANGUAGE.LANGUAGE_ID.eq(languageId)).execute();
    }

    @Cacheable(value = "data", key = "'language:' + #languageId")
    @Override
    public LanguageDTO get(Long languageId) {
        return JooqProvider.dsl().select(LANGUAGE.asterisk())
                .from(LANGUAGE)
                .where(LANGUAGE.LANGUAGE_ID.eq(languageId))
                .fetchOneInto(LanguageDTO.class);
    }
}
